
/* SOURCE-CODE-START */

"use strict";

var globalUtils = (function() {
if (typeof globalUtils !== 'undefined') {
  return globalUtils;
}



function requireMoment() {
  if (typeof moment === 'undefined') {
    throw new Error('moment.js required');
  }
}

function requireLodash() {
  if (typeof _ === 'undefined') {
    throw new Error('lodash.js required');
  }
}

requireLodash();




//
// global-utils 封装常用的方法。
//

/**
 * @namespace globalUtils
 */

var globalUtils = {};
var _privateFn = {};
globalUtils.privateFn = _privateFn;




//
// 判断给定的参数是什么类型
//

/**
 * @memberof globalUtils
 * @description 判断给定参数的值是不是字符串类型
 * @param {*} [arg] 
 * @returns {boolean} 若给定参数的值是字符串则返回 true, 否则返回 false 
 */
globalUtils.isString = function (arg) {
  return (typeof arg === 'string');
};

/**
 * @memberof globalUtils
 * @description 判断给定参数的值是不是数字类型
 * @param {*} [arg] 
 * @returns {boolean} 若给定参数的值是数字则返回 true, 否则返回 false 
 */
globalUtils.isNumber = function (arg) {
  return (typeof arg === 'number');
};

/**
 * @memberof globalUtils
 * @description 判断给定参数的值是不是布尔值类型
 * @param {*} [arg] 
 * @returns {boolean} 若给定参数的值是布尔值则返回 true, 否则返回 false 
 */
globalUtils.isBoolean = function (arg) {
  return (typeof arg === 'boolean');
};

/**
 * @memberof globalUtils
 * @param {*} [arg] 判断给定参数的值是不是对象(包括 null 值)
 * @returns {boolean} 若给定参数的值是对象则返回 true, 反则返回 false
 */
globalUtils.isObject = function (arg) {
  return (typeof arg === 'object');
};

/**
 * @memberof globalUtils
 * @description 判断给定参数的值是不是函数
 * @param {*} [arg] 
 * @returns {boolean} 若给定参数的值是函数则返回 true, 反则返回 false
 */
globalUtils.isFunction = function (arg) {
  return (typeof arg === 'function');
};

/**
 * @memberof globalUtils
 * @param {*} [arg] 判断给定参数的值是不是数组
 * @returns {boolean} 若给定参数的值是数组则返回 true, 反则返回 false
 */
globalUtils.isArray = function (arg) {
  return (arg instanceof Array);
};

/**
 * @memberof globalUtils
 * @param {*} [arg] 判断给定参数的值是不是日期
 * @returns {boolean} 若给定参数的值是日期则返回 true, 反则返回 false
 */
globalUtils.isDate = function (arg) {
  return (arg instanceof Date);
};

/**
 * @memberof globalUtils
 * @description 判断给定参数的值是不是 null/undefined
 * @param {*} [arg] 
 * @returns {boolean} 若给定参数的值是 null/undefined 则返回 true, 否则返回 false
 */
globalUtils.isNullOrUndefined = function (arg) {
  return (arg === null || arg === undefined);
};

/**
 * @memberof globalUtils
 * @description 判断给定参数的值是不是空字符
 * @param {*} [arg] 
 * @returns {boolean} 若给定参数的值不是空字符串则返回 true, 否则返回 false
 */
globalUtils.isNotEmptyString = function (arg) {
  return (globalUtils.isString(arg) && arg.length > 0);
};

/**
 * @memberof globalUtils
 * @description 判断给定参数的值是不是空数组
 * @param {*} [arg]
 * @returns {boolean} 若给定参数的值不是空数组则返回 true, 否则返回 false
 */
globalUtils.isNotEmptyArray = function (arg) {
  return (globalUtils.isArray(arg) && (arg.length > 0));
};

/**
 * @memberof globalUtils
 * @description 判断给定参数的值是不是空对象
 * @param {*} [arg]
 * @returns {boolean} 若给定参数的值不是空对象则返回 true, 否则返回 false
 */
globalUtils.isNotEmptyObject = function (arg) {
  if (globalUtils.isNullOrUndefined(arg) || !globalUtils.isObject(arg)) {
    return false;
  }

  for (var key in arg) {
    return true;
  }

  return false;
};

//
// 提供返回默认值的方法
//

/**
 * @memberof globalUtils
 * @description 若第一个参数不是 null/undefined 则返回第一个参数，否则返回空字符串
 * @param {*} [arg]
 * @returns {string}
 */
globalUtils.emptyStringIfNullOrUndefined = function (arg) {
  if (globalUtils.isNullOrUndefined(arg)) {
    return '';
  }

  return arg;
};

/**
 * @memberof globalUtils
 * @description 若第一个参数不是 null/undefined 则返回第一个参数，否则返回空数组
 * @param {*} [arg]
 * @returns {Array}
 */
globalUtils.emptyArrayIfNullOrUndefined = function (arg) {
  if (globalUtils.isNullOrUndefined(arg)) {
    return [];
  }

  return arg;
};

/**
 * @memberof globalUtils
 * @description 若第一个参数不是 null/undefined 则返回第一个参数，否则返回空对象
 * @param {*} [arg]
 * @returns {object}
 */
globalUtils.emptyObjectIfNullOrUndefined = function (arg) {
  if (globalUtils.isNullOrUndefined(arg)) {
    return {};
  }

  return arg;
};

/**
 * @memberof globalUtils
 * @description 若第一个参数不是 null/undefined 则返回第一个参数，否则返回默认值
 * @param {*} [arg]
 * @param {*} [defaultValue]
 * @returns {object}
 */
globalUtils.defaultValueIfNullOrUndefined = function (arg, defaultValue) {
  if (globalUtils.isNullOrUndefined(arg)) {
    return defaultValue;
  }

  return arg;
};

/**
 * @memberof globalUtils
 * @description 若第一个参数的值是 null 或者去掉空白符为空则返回默认值，否则返回第一个参数的值
 * @param {*} [arg]
 * @param {*} [defaultValue]
 * @returns {*}
 */
globalUtils.defaultValueIfBlankString = function (arg, defaultValue) {
  if (globalUtils.isNullOrUndefined(arg)) {
    return defaultValue;
  }

  if (globalUtils.isString(arg)) {
    var trimedString = globalUtils.trimString(arg);

    if (trimedString.length <= 0) {
      return defaultValue;
    }
  }

  return arg;
};

/**
 * @memberof globalUtils
 * @description 若第一个参数的值是 null 或者是空字符串则返回默认值，否则返回第一个参数的值
 * @param {*} [arg]
 * @param {*} [defaultValue]
 * @returns {*}
 */
globalUtils.defaultValueIfEmptyString = function (arg, defaultValue) {
  if (globalUtils.isNullOrUndefined(arg)) {
    return defaultValue;
  }

  if (globalUtils.isString(arg) && arg.length <= 0) {
    return defaultValue;
  }

  return arg;
};


//
// 处理字符串和对象的方法
//

/**
 * @memberof globalUtils
 * @description 转换给定参数的值成字符串
 * @param {*} [arg]
 * @returns {string} 若参数的值不是 null/undefined 则返回字符串，否则返回 null/undefined
 */
globalUtils.convertToString = function (arg) {
  if (globalUtils.isString(arg)) {
    return arg;
  }

  if (globalUtils.isNullOrUndefined(arg)) {
    return arg;
  }

  return String(arg);
};

/**
 * @memberof globalUtils
 * @description 删除给定参数的值的头尾空白符
 * @param {*} [arg]
 * @returns {*} 若参数的值不是字符串则直接返回，否则返回去掉头尾空白符的字符串
 */
globalUtils.trimString = function (arg) {
  if (globalUtils.isString(arg)) {
    return arg.trim();
  }

  return arg;
};

/**
 * @memberof globalUtils
 * @description 根据给定的字符串格式和参数做字符串格式化
 * @param {string} format 字符串格式的占位符是 {0}、{1}、{2} ...
 * @param {(string[]|...string)} args
 * @returns {string} 返回字符串格式化后的字符串
 */
globalUtils.formatString = function (format, objectArray) {
  if (globalUtils.isNullOrUndefined(format)) {
    throw new Error('argument#0 "format" is null/undefined');
  }

  if (!globalUtils.isString(format)) {
    throw new Error('argument#0 "format" required string');
  }

  if (!(objectArray instanceof Array)) {
    objectArray = [];

    for (var index = 1; index < arguments.length; index++) {
      objectArray.push(arguments[index]);
    }
  }

  // 替换占位符 {数字}
  var newString = format.replace(/\{([0-9]+)\}/g, function (match, index) {
    var argIndex = parseInt(index);
    var arg = objectArray[argIndex];

    return (globalUtils.convertToString(arg) || '');
  });

  return newString;
};





/**
 * @memberof globalUtils
 * @description 合并多个对象的字段到新的对象上(浅度复制)
 * @param {(object[]|...object)} objectArray 
 * @returns {object}
 */
globalUtils.concatObjects = function (objectArray) {
  if (!(objectArray instanceof Array)) {
    objectArray = arguments;
  }

  var newObj = {};

  for (var index = 0; index < objectArray.length; index++) {
    var obj = objectArray[index];

    for (var key in obj) {
      newObj[key] = obj[key];
    }
  }

  return newObj;
};

/**
 * @memberof globalUtils
 * @description 合并多个对象的字段到新的对象上(深度复制)
 * @param {(object[]|...object)} objectArray 
 * @returns {object}
 */
globalUtils.mergeObjects = function (objectArray) {
  if (!(objectArray instanceof Array)) {
    objectArray = arguments;
  }

  var newArgs = [{}];

  for (var index = 0; index < objectArray.length; index++) {
    newArgs.push(objectArray[index]);
  }

  return _.merge.apply(null, newArgs);
};

/**
 * @memberof globalUtils
 * @description 复制并忽略空值的属性
 * @param {*} source 
 * @returns {*}
 */
globalUtils.ignoreObjectEmptyValue = function (source) {
  if (source === null) {
    return null;
  }

  var result;

  if (source instanceof Array) {
    result = [];

    source.forEach(function (value) {
      var newValue = globalUtils.ignoreObjectEmptyValue(value);
      result.push(newValue);
    });
  } else if (globalUtils.isObject(source)) {
    result = {};

    for (var key in source) {
      var value = source[key];

      if (value === null || value === undefined || value === '') {
        //
      } else if ((value instanceof Array) || globalUtils.isObject(value)) {
        result[key] = globalUtils.ignoreObjectEmptyValue(value);
      } else {
        result[key] = value;
      }
    }
  } else {
    result = source;
  }

  return result;
};

/**
 * @memberof globalUtils
 * @description 转换空字符串成 null 值
 * @param {*} source 
 * @returns {*}
 */
globalUtils.convertEmptyStringToNull = function (source) {
  if (source === null || source === '') {
    return null;
  }

  var result;

  if (source instanceof Array) {
    result = [];

    source.forEach(function (value) {
      var newValue = globalUtils.convertEmptyStringToNull(value);
      result.push(newValue);
    });
  } else if (globalUtils.isObject(source)) {
    result = {};

    for (var key in source) {
      var value = source[key];
      var newValue;

      if (value === null || value === '') {
        newValue = null;
      } else if ((value instanceof Array) || globalUtils.isObject(value)) {
        newValue = globalUtils.convertEmptyStringToNull(value);
      } else {
        newValue = value;
      }

      result[key] = newValue;
    }
  } else {
    result = source;
  }

  return result;
};




/**
 * @memberof globalUtils
 * @description 解析日期
 * @param {string} text 
 * @returns {Date}
 */
globalUtils.parseDateWithZone = function (text) {
  if (globalUtils.isNullOrUndefined(text)) {
    return null;
  }

  requireMoment();
  var momentDate = moment(text, 'YYYY-MM-DDZ');
  var date = momentDate.toDate();

  return date;
};

/**
 * @memberof globalUtils
 * @description 解析日期时间
 * @param {string} text 
 * @returns {Date}
 */
globalUtils.parseDateTimeWithZone = function (text) {
  if (globalUtils.isNullOrUndefined(text)) {
    return null;
  }

  requireMoment();
  var momentDate = moment(text, moment.ISO_8601);
  var date = momentDate.toDate();

  return date;
};

/**
 * @memberof globalUtils
 * @description 格式化日期
 * @param {Date} date 
 * @returns {string}
 */
globalUtils.formatDateWithZone = function (date) {
  if (globalUtils.isNullOrUndefined(date)) {
    return null;
  }

  requireMoment();
  var momentDate = moment(date);
  var text = momentDate.format('YYYY-MM-DDZ');

  return text;
};

/**
 * @memberof globalUtils
 * @description 格式化日期时间
 * @param {Date} date 
 * @returns {string}
 */
globalUtils.formatDateTimeWithZone = function (date) {
  if (globalUtils.isNullOrUndefined(date)) {
    return null;
  }

  requireMoment();
  var momentDate = moment(date);
  var text = momentDate.toISOString();

  return text;
};

/**
 * @memberof globalUtils
 * @description 格式化日期
 * @param {Date} date 
 * @returns {string}
 */
globalUtils.formatYearDay = function (date) {
  if (globalUtils.isNullOrUndefined(date)) {
    return null;
  }

  requireMoment();
  var momentDate = moment(date);
  var text = momentDate.format('YYYY-MM-DD');

  return text;
};

/**
 * @memberof globalUtils
 * @description 格式化日期时间
 * @param {Date} date 
 * @returns {string}
 */
globalUtils.formatYearSecond = function (date) {
  if (globalUtils.isNullOrUndefined(date)) {
    return null;
  }

  requireMoment();
  var momentDate = moment(date);
  var text = momentDate.format('YYYY-MM-DD HH:mm:ss');

  return text;
};




// HTML 转义符号的映射关系
var htmlEscapingRules = {
  '&': '&amp;',
  '<': '&lt;',
  '>': '&gt;',
  '"': '&quot;',
  "'": '&#x27;',
  '/': '&#x2F;'
};

// HTML 特殊符号的正则表达式
var htmlSpecialChars = /[&<>"'\/]/g;

/**
 * @memberof globalUtils
 * @description 转义 HTML 特殊字符
 * @param {string} source 
 * @returns {string}
 */
globalUtils.escapeHtml = function (source) {
  if (!globalUtils.isString(source)) {
    return source;
  }

  return source.replace(htmlSpecialChars, function (match) {
    return htmlEscapingRules[match];
  });
};




/**
 * @memberof globalUtils
 * @description 返回完整的 URL 路径
 * @param {string} relativeUrl 
 * @returns {string}
 */
globalUtils.getFullUrl = function (relativeUrl) {
  if (!globalUtils.isString(relativeUrl)) {
    throw new Error('argument#0 "relativeUrl" required string');
  }

  // 获取 base 标签的 href 属性值
  var basePath = $('base').attr('href');

  // basePath 规范成 "/" 结尾
  if (globalUtils.isNullOrUndefined(basePath)) {
    basePath = '/';
  } else if (!basePath.endsWith('/')) {
    basePath = basePath + '/';
  }

  // relativeUrl 规范成不以 "/" 开头
  if (relativeUrl.startsWith('/')) {
    relativeUrl = relativeUrl.substring(1);
  }

  return (basePath + relativeUrl);
};

/**
 * @memberof globalUtils
 * @description 获取浏览器URL
 * @returns {string}
 */
globalUtils.getLocationUrl = function () {
  return location.href;
};


/**
 * @memberof globalUtils
 * @description 改变浏览器URL
 * @param {string} url 
 */
globalUtils.setLocationUrl = function (url) {
  if (!globalUtils.isString(url)) {
    throw new Error('argument#0 "url" required string');
  }

  location.href = url;
};




/**
 * @memberof globalUtils
 * @description 判断表单数据是否相同
 * @param {*} oldData 
 * @param {*} newData 
 * @returns {boolean}
 */
globalUtils.isFormDataEqual = function (oldData, newData) {
  return _.isEqualWith(oldData, newData, function (value, other) {
    if ((globalUtils.isNullOrUndefined(value) || value === '')
      && (globalUtils.isNullOrUndefined(other) || other === '')) {
      return true;
    }

    return undefined;
  });
};



return globalUtils;
})();

/* SOURCE-CODE-END */

export { globalUtils };
